package com.yangchuang.openpicture.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yangchuang.openpicture.bulider.PictureStatsUpdateBuilder;
import com.yangchuang.openpicture.constant.SyncRedisConstants;
import com.yangchuang.openpicture.constant.UserLikePictureRedisConstants;
import com.yangchuang.openpicture.mapper.UserLikePictureMapper;
import com.yangchuang.openpicture.pojo.UserLikePicture;
import com.yangchuang.openpicture.service.*;
import com.yangchuang.openpicture.util.RedisUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import static com.yangchuang.openpicture.util.ShanghaiTimeUtils.getCurrentTimeStr;

@Slf4j
@Service
@RequiredArgsConstructor
public class UserLikePictureServiceImpl extends ServiceImpl<UserLikePictureMapper, UserLikePicture> implements UserLikePictureService {

    private final RedisUtils redisUtils;
    private final PictureStatisticsService pictureStatisticsService;
    private final PictureService pictureService;
    private final UserStatisticsService userStatisticsService;
    // ========== 点赞行为 ==========


    //controller层调用这里的方法
    @Override
    public void toggleLike(Long userId, Long pictureId, Boolean isLike) {
        //采用懒加载的模式 把一次整体初始化”变成多次的懒惰初始化
        //1.user_like_picture的 string-set结构
        // set里面 key:xxx+ user_id   set:喜欢的图片的id(支持自动去重，重复的添加不进去) 这里的key直接区分到user级别就可以
        //不管当前是第一次喜欢 还是之前喜欢过 现在取消喜欢 我们都可以把pictureId加进去 因为set支持自动去重 通常这种做法更加推荐 更高效
        //如果这个用户第一次喜欢某张图片 会自动创建key
        //如果不是 说明key已经存在了 会自动写入  如果是取消喜欢 说明里面已经存在了 会插入失败
        redisUtils.setOps().addMembers(UserLikePictureRedisConstants.USER_LIKE_PICTURE_SET + userId, pictureId);

        //2.user_like_picture的 string-hash结构 string :xxx+userId  和上面的一样 能够区分到每个用户即可
        //hash: 状态 创建时间 更新时间
        //不判断是否存在 而是采用懒加载的模式  setFieldValueIfAbsent 如果没有的话就set(新增) 如果已经有了的话 do nothing
        //这个key要能够区分到某个用户对于某张图片的操作的级别  不然的话 图片之间会互相覆盖 影响
        String key = UserLikePictureRedisConstants.USER_LIKE_PICTURE_HASH + userId + ":" + pictureId;
        //如果这个key对应的这个字段不存在的话--->创建--->用户第一次喜欢这张图片 （不可能是取消喜欢 因为取消喜欢的前提是 喜欢 而 喜欢就会留下记录）
        //如果存在 说明不是第一次 说明之前和这张图片发生过关系
        redisUtils.hashOps().setFieldValueIfAbsent(key, UserLikePictureRedisConstants.USER_LIKE_PICTURE_HASH_FIELD_CREATE_TIME, getCurrentTimeStr());
        redisUtils.hashOps().setFieldValue(key, UserLikePictureRedisConstants.USER_LIKE_PICTURE_HASH_FIELD_STATUS, isLike ? 1 : 0);
        //不管是不是第一次 都是要设置更新时间的
        redisUtils.hashOps().setFieldValue(key, UserLikePictureRedisConstants.USER_LIKE_PICTURE_HASH_FIELD_UPDATE_TIME, getCurrentTimeStr());

        //2.picture_stats结构 hash key:xxx+pictureId hash:一堆统计字段
        new PictureStatsUpdateBuilder(pictureStatisticsService, pictureId)
                .setLike(isLike).execute();
        //3.维护user_stats结构  现在是当前用户主动喜欢/不喜欢某张 不是被动的
        new UserStatsUpdateBuilder(userStatisticsService, userId)
                //不管是主动喜欢或者不喜欢某张图片 浏览量肯定都+1
                .setLike(isLike).setView(true).execute();
        //4.根据picture_id 去查出对应的图片主人的id [ 先去redis  然后mysql  然后添加到redis ]也可以 或者直接每次查询数据库
        String ownerId = pictureService.PictureOwnerUpdate(pictureId);
        //5.维护图片的主人的数据统计情况
        new UserStatsUpdateBuilder(userStatisticsService, userId)
                //不管是主动喜欢或者不喜欢某张图片 浏览量肯定都+1
                .setLike(isLike).setViewed(true).execute();

        //6.这里的话 如果全部使用脏数据机制 来同步的话 那这个user_like_picture也要记录成脏数据 就算是第一次 也是啊
        //这里记录的就是 用户喜欢/不喜欢某张图片了 user_like_picture:对应两种结构 到时候同步的时候需要两种结构一起配合
        //脏数据 我们要到 某个用户：某张图片  key是死的 set:userId + ":" + pictureId 结构 到时候好挑出来吗？？
        redisUtils.setOps().addMembers(SyncRedisConstants.USER_LIKE_PICTURE_DIRTY_SET, userId + ":" + pictureId);
    }
}
